package com.zxy.supplier_system.server.service

import com.zxy.supplier_system.server.controller.ProcurementSupplierPaymentRecordController
import com.zxy.supplier_system.server.entity.ProcurementPaymentRecord
import com.zxy.supplier_system.server.repository.ProcurementItemRepository
import com.zxy.supplier_system.server.repository.ProcurementPaymentRecordRepository
import com.zxy.supplier_system.server.repository.ProcurementReturnItemRepository
import com.zxy.supplier_system.server.repository.ProcurementSupplierRepository
import com.zxy.supplier_system.server.utils.orElse404
import com.zxy.supplier_system.server.utils.toIntIdAndName
import jakarta.transaction.Transactional
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import java.time.OffsetDateTime

@Service
class ProcurementPaymentRecordService(
    private val procurementPaymentRecordRepository: ProcurementPaymentRecordRepository,
    private val procurementSupplierRepository: ProcurementSupplierRepository,
    private val systemServiceService: SystemServiceService,
    private val procurementItemRepository: ProcurementItemRepository,
    private val procurementReturnItemRepository: ProcurementReturnItemRepository,
) {

    @Transactional
    fun pay(
        supplierId: Int,
        request: ProcurementSupplierPaymentRecordController.ProcurementPayRequest
    ): ProcurementPaymentRecord {
        val now = OffsetDateTime.now()
        val procurementPaymentRecord = ProcurementPaymentRecord().apply {
            this.supplier = procurementSupplierRepository.findByIdOrNull(supplierId).orElse404()
            this.money = request.money
            this.paidDateTime = request.paidDateTime ?: now
            this.createdDateTime = now
        }
        return procurementPaymentRecordRepository.save(procurementPaymentRecord)
    }

    fun query(
        supplierId: Int,
        request: ProcurementSupplierPaymentRecordController.QueryProcurementPaymentRecordRequest,
        pageable: Pageable
    ): ProcurementSupplierPaymentRecordController.QueryProcurementPaymentRecordResponsePage {
        val systemService = systemServiceService.getCurrentSystemService()
        val page = this.procurementPaymentRecordRepository.findAll(
            Specification.allOf(
                ProcurementPaymentRecordRepository.systemServiceEqual(systemService),
                ProcurementPaymentRecordRepository.supplierIdEqual(supplierId),
                ProcurementPaymentRecordRepository.paidDateTimeBefore(request.endPaidDateTime),
            ),
            pageable
        ).map {
            ProcurementSupplierPaymentRecordController.QueryProcurementPaymentRecordResponse(
                it.id!!,
                it.supplier.toIntIdAndName(),
                it.createdDateTime,
                it.paidDateTime,
                it.money,
            )
        }
        return ProcurementSupplierPaymentRecordController.QueryProcurementPaymentRecordResponsePage(
            page,
            procurementPaymentRecordRepository.sumTotalPaidMoney(supplierId, request, systemService),
            procurementItemRepository.sumBySupplier(
                supplierId,
                request,
                systemService
            ) - procurementReturnItemRepository.sumBySupplier(supplierId, request, systemService),
        )
    }


    @Transactional
    fun delete(id: Int) {
        this.procurementPaymentRecordRepository.deleteProcurementPaymentRecordByIdAndSupplier_SystemService(
            id,
            systemServiceService.getCurrentSystemService()
        )
    }
}